home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / PHONG.ZIP / SPHERE.C < prev    next >
C/C++ Source or Header  |  1995-10-15  |  5KB  |  195 lines

  1.  
  2. // Phong Shading Demo. By Keith Harrison (CIS:100431,1675). 15th Oct. 1995
  3. // Shades 20 spheres with differing values of Kd (diffuse)
  4. // and Ks (specular) properties.
  5. // Program uses single equation shading, evaluating only the red component.
  6. // Uses Watcom's graphics library (graph.h)
  7.  
  8. // Phong's equation for Intensity:
  9. // I = IaKa + Ii[Kd(L.N) + Ks(N.H)ⁿ] / (r + K)
  10.  
  11. // Developed with Watcom V10.0a from the MS Windows version
  12. // (the Windows version plotted 24bit colour values).
  13.  
  14. // Based on information in 'Fundamentals of Three-Dimensional Computer
  15. // Graphics' by Alan Watt, ISBN 0 201 15442 0.
  16.  
  17. #include <conio.h>
  18. #include <graph.h>
  19. #include <math.h>
  20.  
  21. //Function prototypes.
  22. void setpalette(void);
  23. void plotpixel(short x, short y, short colour);
  24.  
  25. void ShadeSphere(float Kd, float Ks,
  26.                  short SpecIndex, short Xcentre, short Ycentre, short radius);
  27.  
  28. void CalculateLNandNnH( short x,  short y, short z, short SpecIndex,
  29.                         float xn, float yn, float zn,
  30.                         float *LdotN, float *dist, float *NnH);
  31.  
  32. //Ambient light intensity (0 to 1)
  33. const float IaKa = 0.2;
  34.  
  35. //Vector H is the unit normal to the hypothetical surface oriented
  36. //halfway between the light direction vector (L) and the viewing vector (V).
  37. const float Hx = 0.326058, Hy = 0.325058, Hz = 0.888074;
  38.  
  39. //Intensity of light source.
  40. const short Ilight = 140;
  41. //Light source distance factor.
  42. const float K = 70;
  43. //Light source position.
  44. const float dx = 110, dy = 110, dz = 110;
  45. //Light source normal.
  46. const float Lx = 0.57735, Ly = 0.57735, Lz = 0.57735;
  47.  
  48. long palette[256];
  49.  
  50. void setpalette(void)
  51. {
  52.   short i;  
  53.  
  54.   //The VGA can only handle 64 different shades of red.
  55.   for (i=0; i<64; i++)
  56.     palette[i] = (long)i;
  57.  
  58.   _remapallpalette( &palette);
  59. };
  60.  
  61.  
  62.  
  63. void plotpixel(short x, short y, short colour)
  64. {
  65.   _setcolor(colour);
  66.   _setpixel(x, y);
  67. };
  68.  
  69.  
  70.  
  71. void CalculateLNandNnH( short x,  short y, short z, short SpecIndex,
  72.                         float xn, float yn, float zn,
  73.                         float *LdotN, float *dist, float *NnH)
  74. {
  75.   float NH;
  76.  
  77.   *LdotN = xn*Lx + yn*Ly + zn*Lz;
  78.  
  79.   if (LdotN <= 0)
  80.     LdotN = 0;
  81.   else {
  82.     *dist = sqrt((dx - x)*(dx - x) + (dy - y)*(dy - y) + (dz - z)*(dz - z));
  83.     NH = Hx*xn + Hy*yn + Hz*zn;
  84.     *NnH = exp(SpecIndex*log(NH));
  85.   }
  86. };
  87.  
  88.  
  89.  
  90. void ShadeSphere(float Kd, float Ks,
  91.                  short SpecIndex, short Xcentre, short Ycentre, short radius)
  92. {
  93.   short Ir, Igb; // Ir = intensity of Red, Igb = intensity of green/blue.
  94.   int x, y, z; // Coordinates of point on sphere surface.
  95.   float rsquare, xsquare, ysquare, zsquare, denom, xn, yn, zn, LdotN, NnH,
  96.         dist, distfactor, ambientterm, diffuseterm, specularterm; 
  97.  
  98.   rsquare = radius * radius;
  99.  
  100.   for (y = -radius; y<radius; y++) {
  101.     ysquare = y * y;  
  102.     for (x = -radius; x<radius; x++) {
  103.       xsquare = x * x;
  104.       if ( (xsquare + ysquare) <= rsquare) {
  105.         z = sqrt(rsquare - xsquare - ysquare);
  106.         zsquare = z * z;
  107.         denom = sqrt(xsquare + ysquare + zsquare);
  108.         // xn, yn, and zn are unit normals from the sphere surface.
  109.         xn = x / denom;
  110.         yn = y / denom;
  111.         zn = z / denom;
  112.         CalculateLNandNnH(x, y, z, SpecIndex, xn, yn, zn, &LdotN, &dist, &NnH); 
  113.         ambientterm = IaKa;
  114.         if (LdotN <= 0) {
  115.           //Point is not illuminated by light source. 
  116.           //Use only ambient component.
  117.           Ir = 64 * ambientterm;
  118.           Igb = 0;
  119.         }
  120.         else {
  121.           distfactor = Ilight / (dist + K);
  122.           diffuseterm = distfactor * Kd * LdotN;
  123.           specularterm = distfactor * Ks * NnH;
  124.           Ir = 64 * (ambientterm + diffuseterm + specularterm);
  125.           Igb = 64 * specularterm;
  126.         };
  127.         plotpixel(Xcentre + x, Ycentre + y, Ir);
  128.       }
  129.     }
  130.   }
  131.  
  132. };
  133.  
  134.  
  135.  
  136. int main(int argc, char *argv[])
  137. {
  138.   short SpecIndex, i, j, Xpos, Ypos;
  139.   float Kd, Ks;
  140.  
  141.   int videomode;
  142.   
  143.   if (argc != 2) {
  144.     printf("\nPhong Shaded Spheres.\n");
  145.     printf("By Keith Harrison.\n\n");
  146.     printf("Usage: sphere <video_mode>\n");
  147.     printf("Video modes: 320  =  320 x 200 x 256 colour (VGA)\n");
  148.     printf("             640  =  640 x 480 x 256 colour (SVGA)\n");
  149.     printf("             800  =  800 x 600 x 256 colour (SVGA)\n");
  150.     printf("             1024 = 1024 x 768 x 256 colour (SVGA)\n\n");
  151.     return 1;
  152.   };
  153.  
  154.   videomode = atoi(argv[1]);
  155.  
  156.   switch (videomode) {
  157.     case 320:  _setvideomode( _MRES256COLOR ); break;
  158.     case 640:  _setvideomode( _VRES256COLOR ); break;
  159.     case 800:  _setvideomode( _SVRES256COLOR ); break;
  160.     case 1024: _setvideomode( _XRES256COLOR ); break;
  161.     default:  
  162.       printf("\nIncorrect command line option.\n");
  163.       printf("Defaulting to 640 x 480 x 256 colours\n");
  164.       printf("Type 'sphere' to see options\n");
  165.       printf("Press any key to continue.\n");
  166.       getch();
  167.       _setvideomode( _VRES256COLOR ); break;
  168.   };
  169.  
  170.   setpalette();
  171.  
  172.   SpecIndex = 9;
  173.   Ypos = 50;
  174.  
  175.   for (i=0; i<4; i++) {
  176.     Xpos = 50;
  177.     Kd = 0;
  178.     Ks = 1;
  179.     for(j=0; j<5; j++) {
  180.       ShadeSphere(Kd, Ks, SpecIndex, Xpos, Ypos, 50);
  181.       Kd += 0.25;
  182.       Ks -= 0.25;
  183.       Xpos += 110;
  184.     };
  185.     Ypos += 110;
  186.     SpecIndex = SpecIndex * 2;
  187.   };
  188.  
  189.   getch();
  190.   _setvideomode( _DEFAULTMODE );
  191.  
  192.   return 0;
  193.  
  194. }
  195.